<?php
declare(strict_types=1);

namespace app\shop\logic;

use app\shop\enums\order\OrderPayStatus;
use app\shop\enums\payment\OrderType;
use app\shop\enums\payment\TradeState;
use app\shop\enums\recharge\RechargeType;
use app\shop\enums\user\UserMoneyChangeType;
use app\shop\exception\FailException;
use app\shop\job\ConfirmOrderPayStatusJob;
use app\shop\library\calculate\Calculate;
use app\shop\library\pay\PayProvider;
use app\shop\library\ShopAuth;
use app\shop\library\ShopHelper;
use app\shop\model\PaymentTradeModel;
use app\shop\model\recharge\RechargeOrderModel;
use app\shop\model\recharge\RechargePlanModel;
use app\shop\service\DeliveryService;
use app\shop\service\LogService;
use app\shop\service\OrderService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use think\facade\Queue;
use think\Paginator;
use Throwable;

/**
 * @property RechargeOrderModel $model
 */
class RechargeLogic extends BaseLogic
{
    public function __construct()
    {
        $this->model = new RechargeOrderModel();
    }

    /**
     * 充值中心
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function rechargeCenter(): array
    {
        $query = RechargePlanModel::query();

        $query->field(['id', 'money', 'gift_money']);

        $query->order('weigh', 'desc');

        $planList = $query->select()->toArray();

        return [
            'planList' => $planList
        ];
    }

    /**
     * 充值操作
     * @param array $params
     * @return array
     * @throws FailException
     */
    public function recharge(array $params): array
    {
        $planId = $params['plan_id'] ?? 0;
        $payWay = $params['pay_way'] ?? '';

        if ($planId) {
            // 套餐充值
            $plan = RechargePlanModel::where('id', $params['plan_id'])->findOrEmpty();
            if ($plan->isEmpty()) {
                throw new FailException('充值套餐方案有误');
            }
            $plan = $plan->toArray();

            $amount     = $plan['money'];
            $giftAmount = $plan['gift_money'];
            $type       = RechargeType::PLAN;
        } else {
            // 自定义充值金额
            $amount     = $params['custom_amount'];
            $giftAmount = 0;
            $type       = RechargeType::CUSTOM;
        }

        $orderService = new OrderService();

        $orderNo    = $orderService->generateOrderNo();
        $outTradeNo = $orderService->generateOrderNo('CZ');

        $orderData = [
            'order_no'      => $orderNo,
            'out_trade_no'  => $outTradeNo,
            'user_id'       => ShopAuth::instance()->getUser()->id,
            'recharge_type' => $type,
            'money'         => $amount,
            'gift_money'    => $giftAmount,
            'pay_price'     => $amount,
            'actual_money'  => Calculate::newDecimal($amount)->add($giftAmount)->getValue(),
            'pay_way'       => $payWay,
            'pay_status'    => OrderPayStatus::UNPAID,
            'source'        => ShopAuth::instance()->getUserSourceClient(),
        ];

        RechargeOrderModel::startTrans();
        try {
            $order = RechargeOrderModel::create($orderData);

            $payProvider = new PayProvider($payWay);
            $result      = $payProvider->pay([
                'user_id'      => $order->user_id,
                'amount'       => $order->pay_price,
                'source'       => $order->source,
                'out_trade_no' => $outTradeNo,
                'desc'         => '充值订单',
                'quit_url'     => ShopHelper::full_h5_url('/pagesMember/pages/balance/balance'),
                'return_url'   => ShopHelper::full_h5_url('/pagesOrder/pages/recharge/list'),
            ]);

            $paymentTrade = PaymentTradeModel::create([
                'out_trade_no' => $outTradeNo,
                'order_type'   => OrderType::RECHARGE,
                'order_id'     => $order->id,
                'order_no'     => $order->order_no,
                'user_id'      => $order->user_id,
                'source'       => $order->source,
                'pay_price'    => $order->pay_price,
                'pay_way'      => $payWay,
                'pay_params'   => ShopHelper::array_to_json($result),
                'trade_state'  => TradeState::UNPAID,
            ]);

            Queue::later(30, ConfirmOrderPayStatusJob::class, ['payment_id' => $paymentTrade->id], ConfirmOrderPayStatusJob::$queue);

            RechargeOrderModel::commit();
        } catch (Throwable $e) {
            throw new FailException('充值失败,请稍后再试', null, $e);
        }

        return $result;
    }

    public function removeObstacles($params)
    {

        $order_id = $params['user_id'].'S'.$params['id'].'S'.rand(100000, 999999);
        $price = Db::name('distribution_card')->where('id',$params['id'])->value('price');
        $payWay = isset($params['pay_way'])?$params['pay_way']:'alipay';
        $orderService = new OrderService();
        $outTradeNo = $orderService->generateOrderNo('CZ');
        $orderNo    = $orderService->generateOrderNo();
        RechargeOrderModel::startTrans();
        try {
            $payProvider = new PayProvider('alipay');
            $result      = $payProvider->pay([
                'user_id'      => $params['user_id'],
                'amount'       => $price,
                'source'       => 'h5',
                'out_trade_no' => $order_id,
                'desc'         => '购买会员卡',
                'quit_url'     => ShopHelper::full_h5_url('/pages/my/components/vip'),
                'return_url'   => ShopHelper::full_h5_url('/pages/my/my'),
            ]);
            $paymentTrade = PaymentTradeModel::create([
                'out_trade_no' => $order_id,
                'order_type'   => OrderType::VIP,
                'order_id'     => $params['user_id'],
                'order_no'     => $order_id,
                'user_id'      => $params['user_id'],
                'source'       => 'h5',
                'pay_price'    => $price,
                'pay_way'      => $payWay,
                'pay_params'   => ShopHelper::array_to_json($result),
                'trade_state'  => TradeState::UNPAID,
            ]);

            Queue::later(30, ConfirmOrderPayStatusJob::class, ['payment_id' => $paymentTrade->id], ConfirmOrderPayStatusJob::$queue);
            RechargeOrderModel::commit();
        }catch (\Exception $e){
            throw new FailException('购买失败,请稍后再试', null, $e);
        }

        return $result;
        if($price == 0){
            return $this->model->cardPayAfter($order_id,$price);
        }else{
            //微信支付
            return $this->model->cardPayAfter($order_id,$price);
        }
    }


    /**
     * 处理充值回调
     * @param int|string $orderId
     * @return void
     * @throws FailException
     */
    public function processRechargeOrder(int|string $orderId): void
    {
        $this->model->startTrans();
        try {
            $order = RechargeOrderModel::where('id', $orderId)->with(['payment_trade', 'user'])->findOrEmpty()
                ->visible([
                    'user'          => ['openid'],
                    'payment_trade' => ['trade_no']
                ]);

            LogService::userMoneyLog($order->user_id, $order->money, $order->order_no, UserMoneyChangeType::RECHARGE);
            if ($order->gift_money > 0) {
                LogService::userMoneyLog($order->user_id, $order->gift_money, $order->order_no, UserMoneyChangeType::SYSTEM_GIVE);
            }
            $order->pay_status = OrderPayStatus::PAID;
            $order->pay_time   = time();
            $order->save();

            if ($order['payment_trade']['source'] == 'miniapp') {
                $this->syncDeliveryToMiniapp($order['payment_trade']['trade_no'], $order['user']['openid']);
            }

            $this->model->commit();
        } catch (Throwable $e) {
            $this->model->rollback();
            throw new FailException('余额充值失败', null, $e, ['order_id' => $orderId], true);
        }
    }

    /**
     * 同步到小程序发货管理
     * @param string $tradeNo
     * @param string $openid
     * @return void
     * @throws FailException
     */
    private function syncDeliveryToMiniapp(string $tradeNo, string $openid): void
    {
        $deliveryService = new DeliveryService();

        $options = $deliveryService->buildVirtualDeliveryOptionsSyncToMiniapp($tradeNo, $openid, '平台余额充值');

        $deliveryService->requestSyncDeliveryInfo($options);

        $deliveryService->setReceiveJumpPath('pagesOrder/pages/center/center');
    }

    /**
     * 充值订单列表
     * @param array $params
     * @return Paginator|array
     */
    public function getOrderList(array $params): Paginator|array
    {
        $query = $this->model::getQuery();

        $query->where([
            ['user_id', '=', $params['user_id']]
        ]);

        $query->field(['id', 'order_no', 'money', 'gift_money', 'actual_money', 'create_time', 'pay_status']);

        $query->order('id', 'desc');

        return $this->model::paginateListQuery($query);
    }
}